
package cn.com.agree.common.util;

import cn.com.agree.common.constant.GloPropertyConstant;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.ResourceUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;




/**
 * 
 * @ClassName: FileUtil
 * @company 赞同科技
 * @author xrp09
 * 
 */
public class FileUtil {
	private static Log logger = LogFactory.getLog(FileUtil.class);
	
	public final static String encoding = "UTF-8";



    public static String  transformfile(String pathname)throws Exception{
        File file = new File(pathname);
        if (!file.exists()) {
            throw new Exception("文件不存在！");
        }
        return pathname;
    }
    /**
     * 下载文件名重新编码
     *
     * @param request 请求对象
     * @param fileName 文件名
     * @return 编码后的文件名
     */
    public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException
    {
        final String agent = request.getHeader("USER-AGENT");
        String filename = fileName;
        if (agent.contains("MSIE"))
        {
            // IE浏览器
            filename = URLEncoder.encode(filename, "utf-8");
            filename = filename.replace("+", " ");
        }
        else if (agent.contains("Firefox"))
        {
            // 火狐浏览器
            filename = new String(fileName.getBytes(), "ISO8859-1");
        }
        else if (agent.contains("Chrome"))
        {
            // google浏览器
            filename = URLEncoder.encode(filename, "utf-8");
        }
        else
        {
            // 其它浏览器
            filename = URLEncoder.encode(filename, "utf-8");
        }
        return filename;
    }

    /**
     * 输出指定文件的byte数组
     *
     * @param filePath 文件路径
     * @param os 输出流
     * @return
     */
    public static void writeBytes(String filePath, OutputStream os) throws IOException
    {
        FileInputStream fis = null;
        try
        {
            File file = new File(filePath);
            if (!file.exists())
            {
                throw new FileNotFoundException(filePath);
            }
            fis = new FileInputStream(file);
            byte[] b = new byte[1024];
            int length;
            while ((length = fis.read(b)) > 0)
            {
                os.write(b, 0, length);
            }
        }
        catch (IOException e)
        {
            throw e;
        }
        finally
        {
            if (os != null)
            {
                try
                {
                    os.close();
                }
                catch (IOException e1)
                {
                    e1.printStackTrace();
                }
            }
            if (fis != null)
            {
                try
                {
                    fis.close();
                }
                catch (IOException e1)
                {
                    e1.printStackTrace();
                }
            }
        }
    }

	/**
	 * 
	 * @Title： BuffWrite
	 * @param fileList
	 * @param filePath
	 * @return boolean
	 * @throws Exception
	 */
	public static boolean BuffWrite(ArrayList<String> fileList, String filePath) {
		try {
			FileOutputStream fw = new FileOutputStream(filePath);
			BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fw, "iso8859-1"));
			for (int i = 0; i < fileList.size(); i++) {
				bw.write(fileList.get(i) + "");
				bw.write("\n");
			}
			bw.flush();
			bw.close();
			fw.close();
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		} finally {

		}
		return true;
	}

	/**
	 * 将内容写到文本中
	 * @param filePath 要写入到的目标文件路径
	 * @param fileContent 要写入的内容
	 * @return
	 */
	public static boolean writeFile(String fileContent, String filePath) {
		boolean flag = true;
		FileOutputStream os = null;
		try {
			if (filePath.contains("\\")){
				filePath=filePath.replaceAll("\\\\","/");

			}
			File file = new File(filePath);
			if(!file.exists()){
				createFileByfileName(filePath.substring(0, filePath.lastIndexOf("/")),filePath.substring(filePath.lastIndexOf("/"), filePath.length()));
			}
			os = new FileOutputStream(filePath);
			byte[] b = fileContent.getBytes();
			os.write(b, 0, b.length);
		} catch (IOException e) {
			flag = false;
			e.printStackTrace();
			logger.error(e.getMessage(), e);
		} finally {
			try {
				if (os != null) {
					os.flush();
					os.close();
				}
			} catch (IOException e) {
				flag = false;
				e.printStackTrace();
				logger.error(e.getMessage(), e);
			}
		}
		return flag;
	}

	/**
	 * 根据指定字符集将内容写到文本中
	 * @param filePath 要写入到的目标文件路径
	 * @param fileContent 要写入的内容
	 * @param encoding 字符集
	 * @return
	 */
	public static boolean writeFileEncoding(String fileContent, String filePath, String encoding) {
		boolean flag = true;
		FileOutputStream os = null;
		try {
			os = new FileOutputStream(filePath);
			byte[] b = fileContent.getBytes(encoding);
			os.write(b, 0, b.length);
		} catch (IOException e) {
			flag = false;
			e.printStackTrace();
			logger.error(e.getMessage(), e);
		} finally {
			try {
				if (os != null) {
					os.flush();
					os.close();
				}
			} catch (IOException e) {
				flag = false;
				e.printStackTrace();
				logger.error(e.getMessage(), e);
			}
		}
		return flag;
	}
	
	
	
	/**
	 * 删除单个文件
	 * @Title： deleteFile
	 * @param filePath 要删除的文件
	 * @return boolean 单个文件删除成功返回true，否则返回false
	 */
	public static boolean deleteFile(String filePath) {
		File file = new File(filePath);
		// 如果文件路径所对应的文件存在，并且是一个文件，则直接删除
		if (file.exists() && file.isFile()) {
			if (file.delete()) {
				logger.debug("删除单个文件" + filePath + "成功！");
				return true;
			} else {
				logger.debug("删除单个文件" + filePath + "失败！");
				return false;
			}
		} else {
			logger.debug("删除单个文件失败：" + filePath + "不存在！");
			return false;
		}
	}

	/**
	 * 删除指定文件路径下面的所有文件和文件夹
	 * @param file
	 */
	public static boolean deleteFiles(File file) {
		boolean flag = false;
		try {
			if (file.exists()) {
				if (file.isDirectory()) {
					String[] contents = file.list();
					for (int i = 0; i < contents.length; i++) {
						File file2X = new File(file.getAbsolutePath() + File.separator + contents[i]);
						if (file2X.exists()) {
							if (file2X.isFile()) {
								flag = file2X.delete();
							} else if (file2X.isDirectory()) {
								deleteFiles(file2X);
							}
						} else {
							logger.debug("删除文件或文件夹失败！" + file + "不存在！");
							flag = false;
						}
					}
				}
				flag = file.delete();
			} else {
				logger.debug("删除文件或文件夹失败！" + file + "不存在！");
				flag = false;
			}
		} catch (Exception e) {
			flag = false;
			e.printStackTrace();
			logger.error("删除文件或文件夹" + file + "失败！ 原因：" + e.getMessage());
		}
		return flag;
	}
	
	/**
	 * 删除指定文件路径下面的所有文件和文件夹
	 * self false 删除不包含自身
	 * @param file
	 */
	public static boolean deleteFiles(File file,boolean self) {
		if(!self){
			boolean flag = false;
			try {
				if (file.exists()) {
					if (file.isDirectory()) {
						String[] contents = file.list();
						for (int i = 0; i < contents.length; i++) {
							File file2X = new File(file.getAbsolutePath() + File.separator + contents[i]);
							if (file2X.exists()) {
								if (file2X.isFile()) {
									flag = file2X.delete();
								} else if (file2X.isDirectory()) {
									deleteFiles(file2X);
								}
							} else {
								logger.debug("删除文件或文件夹失败！" + file + "不存在！");
								flag = false;
							}
						}
					}
				} else {
					logger.debug("删除文件或文件夹失败！" + file + "不存在！");
					flag = false;
				}
			} catch (Exception e) {
				flag = false;
				e.printStackTrace();
				logger.error("删除文件或文件夹" + file + "失败！ 原因：" + e.getMessage());
			}
			return flag;
		}else{
			return deleteFiles(file);
		}
		
	}
	
	/**
	 * 通过文件路径和文件名称创建一个空文件
	 * @param path
	 * @param fileName
	 * @return
	 */
	public static boolean createFileByfileName(String path,String fileName){
		File file = null;
		try {
			file = new File(path);
			if (!file.exists()) {
				file.mkdirs();
			}
			File file2 = new File(path + fileName);
			return file2.createNewFile();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			logger.error(e.getMessage());
			return false;
		}finally {
			file = null;
		}
	}

	/**
	 * 根据路径创建一系列的目录
	 * @param path
	 */
	public static boolean mkDirectory(String path) {
		File file = null;
		try {
			file = new File(path);
			File file1 =file.getAbsoluteFile();

			if (!file1.exists()) {
				file1.setWritable(true, false);
				return file1.mkdirs();
			}
		} catch (RuntimeException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		} finally {
			file = null;
		}
		return false;
	}

	/**
	 * 判断文件是否存在
	 * @param fileName 文件名
	 * @param dir 文件路径
	 * @return
	 */
	public static boolean isFileExist(String fileName, String dir) {
		File file = new File(dir + fileName);
		return (file.exists()) ? true : false;
	}
	/**
	 * 判断文件夹下是否有文件
	 * @param
	 * @param dir 文件路径
	 * @return
	 */
	public static boolean isFileExist(String dir) {
		File file = new File(dir);		
		return file.listFiles().length > 0 ? true : false;
	}
	/**
	 * 获得文件后缀名包含"."
	 * @param fileName 文件名
	 * @return
	 */
	public static String getFileExp(String fileName) {
		String exp = "";
		try {
			exp = fileName.substring(fileName.lastIndexOf("."));// 上传文件的后缀名
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			logger.error(e.getMessage());
		}
		return exp;
	}

	/**
	 * 获得随机文件名,保证在同一个文件夹下不同名
	 * @param fileName 文件名
	 * @param dir 文件路径
	 * @return 返回随机的文件名
	 */
	public static String getRandomName(String fileName, String dir) {
		String exp = getFileExp(fileName);
		Random random = new Random();
		int add = random.nextInt(1000000); // 产生随机数10000以内
		while (isFileExist(fileName + add, dir)) {
			add = random.nextInt(1000000);
		}
		return fileName + add + exp;
	}

	
	/**
	 * 复制文件
	 * @param from 代表的是复制的源文件
	 * @param to 代表目标文件
	 * @return void
	 * @throws Exception
	 */
	public static void copyFile(String from, String to) throws Exception {
		try {
			File file_from = new File(from);
			FileInputStream in = new FileInputStream(file_from);

			File file_to = new File(to);
			if (!file_to.exists()) {
				String ls_to_parent = file_to.getParent();
				File file_to_parent = new File(ls_to_parent);
				file_to_parent.mkdirs();
			}
			FileOutputStream out = new FileOutputStream(file_to);
			byte[] buf = new byte[128 * 1024];
			int c;
			while (true) {
				c = in.read(buf);
				if (c == -1) {
					break;
				}
				out.write(buf, 0, c);
			}
			in.close();
			out.close();
			logger.debug("复制单个文件成功：" + file_to);
		} catch (Exception ex) {
			logger.error("文件复制错误!");
			throw new Exception("文件复制错误!");
		}
	}
	
	/**
	 * 重命名文件
	 * @param dir 文件路径
	 * @param oldfilename 原文件名称
	 * @param newfilename 新文件名称
	 * @return void
	 * @throws Exception
	 */
	public static void renameFile(String dir, String oldfilename, String newfilename) throws Exception {
		try {
			File oldfile = new File(dir+oldfilename);
			File onewfile = new File(dir+newfilename);
			oldfile.renameTo(onewfile);
		} catch (Exception e) {
			logger.error("文件重名名错误!", e);
			throw new Exception("文件重命名错误!");
		}
	}

	/**
	 * 判断文件类型是否是合法的,就是判断allowTypes中是否包含contentType
	 * @param contentType 文件类型
	 * @param allowTypes 文件类型列表
	 * @return 是否合法
	 */
	public static boolean isValid(String contentType, String[] allowTypes) {
		if (null == contentType || "".equals(contentType)) {
			return false;
		}
		for (String type : allowTypes) {
			if (contentType.equals(type)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 移动文件
	 * @Title： moveFile
	 * @param from 代表要移动的源文件
	 * @param to 代表目标文件
	 * @return boolean 移动成功返回true
	 * @throws Exception
	 */
	public static boolean moveFile(String from, String to) throws Exception {
		File file_from = new File(from);
		FileInputStream in = new FileInputStream(file_from);
		File file_to = new File(to);
		if (!file_to.exists()) {
			String ls_to_parent = file_to.getParent();
			File file_to_parent = new File(ls_to_parent);
			file_to_parent.mkdirs();
		}

		FileOutputStream out = new FileOutputStream(file_to);

		byte[] buf = new byte[128 * 1024];
		int c;

		while (true) {
			c = in.read(buf);
			if (c == -1) {
				break;
			}
			out.write(buf, 0, c);
		}

		in.close();
		out.close();
		if (file_to.length() >= 0) {
			file_from.delete();
		}
		return true;
	}

	/**
	 * 判断文件名是否已经存在，如果存在则在后面家(n)的形式返回新的文件名，否则返回原始文件名 例如：已经存在文件名 log4j.htm 则返回log4j(1).htm
	 * @param fileName  文件名不包含路径
	 * @return 判断后的文件名
	 */
	public static String checkFileName(String fileName, String dir) {
		boolean isDirectory = new File(dir + fileName).isDirectory();
		if (isFileExist(fileName, dir)) {
			int index = fileName.lastIndexOf(".");
			StringBuffer newFileName = new StringBuffer();
			String name = isDirectory ? fileName : fileName.substring(0, index);
			String exp = isDirectory ? "" : fileName.substring(index);
			int nameNum = 1;
			while (true) {
				newFileName.append(name).append("(").append(nameNum).append(")");
				if (!isDirectory) {
					newFileName.append(exp);
				}
				if (isFileExist(newFileName.toString(), dir)) {
					nameNum++;
					newFileName = new StringBuffer();
					continue;
				}
				return newFileName.toString();
			}
		}
		return fileName;
	}

	/**
	 * 返回上传的结果，成功与否
	 * @param uploadFileName 上传的文件名
	 * @param savePath 要保存到的路径
	 * @param uploadFile 上传的文件流
	 * @return 成功与否
	 */
	public static boolean upload(String uploadFileName, String savePath, File uploadFile) {
		boolean flag = false;
		try {
			uploadForName(uploadFileName, savePath, uploadFile);
			flag = true;
		} catch (IOException e) {
			flag = false;
			e.printStackTrace();
			logger.error(e.getMessage(),e);
		}
		return flag;
	}

	/**
	 * 上传文件并返回上传后的文件名
	 * @param uploadFileName  被上传的文件名称
	 * @param savePath 文件的保存路径
	 * @param uploadFile 被上传的文件
	 * @return 上传后的文件名
	 * @throws IOException
	 */
	public static String uploadForName(String uploadFileName, String savePath, File uploadFile) throws IOException {
		String newFileName = checkFileName(uploadFileName, savePath);
		FileOutputStream fos = null;
		FileInputStream fis = null;
		try {
			fos = new FileOutputStream(savePath + newFileName);
			fis = new FileInputStream(uploadFile);
			byte[] buffer = new byte[1024];
			int len = 0;
			while ((len = fis.read(buffer)) > 0) {
				fos.write(buffer, 0, len);
			}
		} catch (FileNotFoundException e) {
			logger.error(e.getMessage(),e);
			throw e;
		} catch (IOException e) {
			logger.error(e.getMessage(),e);
			throw e;
		} finally {
			try {
				if (fos != null) {
					fos.close();
				}
				if (fis != null) {
					fis.close();
				}
			} catch (IOException e) {
				logger.error(e.getMessage(),e);
				throw e;
			}
		}
		return newFileName;
	}
	
	/**
	 * 根据文件路径读文件，将文件内容存储到字符串中
	 * @param path
	 * @return
	 */
	public static String readFile(String path) throws Exception {
		String fileContent = "";
		FileInputStream fis = new FileInputStream(path);
		try {
			InputStreamReader isr = new InputStreamReader(fis);
			BufferedReader br = new BufferedReader(isr);
			String line = null;
			while ((line = br.readLine()) != null) {
				fileContent += line;
				fileContent += "\r\n";
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			fis.close();
		}
		return fileContent;
	}

	/**
	 * 根据文件路径安指定字符集读文件，将文件内容存储到字符串中
	 * @param path
	 * @return
	 */
	public static String readFile(String path, String encoding) throws Exception {
		String fileContent = "";
		BufferedReader br=null;
		FileInputStream fis = new FileInputStream(path);
		try {
			InputStreamReader isr = new InputStreamReader(fis, encoding);
			br = new BufferedReader(isr);
			String line = null;
			while ((line = br.readLine()) != null) {
				fileContent += line;
				fileContent += "\r\n";
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			fis.close();
			br.close();
		}
		return fileContent;
	}
	
	/**
	 * 根据文件对象，将文件内容存储到字符串中
	 * @param file
	 * @param encoding
	 * @return
	 * @throws Exception
	 */
	public static String readFile(File file, String encoding) throws Exception {
		String fileContent = "";
		FileInputStream fis = new FileInputStream(file);
		BufferedReader br =null;
		try {
			InputStreamReader isr = new InputStreamReader(fis, encoding);
			br = new BufferedReader(isr);
			String line = null;
			while ((line = br.readLine()) != null) {
				fileContent += line;
				fileContent += "\r\n";
			}
			
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			fis.close();
			br.close();
		}
		return fileContent;
	}

	/**
	 * 获取项目根路径
	 *
	 * @return
	 */
	public static String getResourceBasePath() {
		// 获取跟目录
		File path = null;
		try {
			path = new File(ResourceUtils.getURL("classpath:").getPath());
		} catch (FileNotFoundException e) {
			// nothing to do
		}
		if (path == null || !path.exists()) {
			path = new File("");
		}

		String pathStr = path.getAbsolutePath();
		// 如果是在eclipse中运行，则和target同级目录,如果是jar部署到服务器，则默认和jar包同级
		pathStr = pathStr.replace("\\target\\classes", "");

		return pathStr;
	}


	public static void main(String args[]) {
		try {
			System.out.println("---------------------");
			System.out.println(getResourceBasePath());

			String path = System.getProperty("user.dir");
			System.out.println(path);
			System.out.println("------------------------全部转换----------------------------");
			String lic = path+File.separator+ GloPropertyConstant.LICENSE_FILENAME;
			System.out.println("lic路径是："+lic);

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	

	/**TODO 读取配置文件返回数据集合
	 * @return
	 */
	public static Map<String,String> readProp(){
		Properties prop= new Properties();
		Map<String,String> resmap=new HashMap<String,String>();
		try {
			prop.load(FileUtil.class.getResourceAsStream("/conf.properties"));
			Enumeration<String> names = (Enumeration<String>)prop.propertyNames();
			while (names.hasMoreElements()) {
				String name = names.nextElement();
				String value = prop.getProperty(name);
				resmap.put(name, value);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return resmap;
	}
	
    private static final String AT_LINUX = "L";
    

	/**
     * 记录执行日志
     * @param executeLog 日志内容
     * @param tradeCode	交易代码
     * @return
     */
    public static String writeExecuteLog(String executeLog, String tradeCode) {
    	String filePath = "";
		FileOutputStream os = null;
		try {
			filePath =  "/" + tradeCode + "/";// + caseID + "/";
	    	File file = new File("" + filePath).getAbsoluteFile();
			if (!file.exists()) {
				file.setWritable(true, false);
				file.mkdirs();
			}
			String absoluteFilePath = file.getAbsolutePath()+"/";
	    	synchronized (filePath) {
	    		String name = String.valueOf(System.currentTimeMillis()) + ".txt";
	    		filePath += name;
	    		absoluteFilePath += name;
			}

	    	logger.info("日志文件的存放路径为----"+absoluteFilePath);
			byte[] fileByte = executeLog.getBytes("UTF-8");
			os = new FileOutputStream(absoluteFilePath);
			os.write(fileByte, 0, fileByte.length);
			os.flush();
			return filePath;
		} catch(Exception e) {
			logger.error("文件[" + filePath + "]写入失败。" + e.getMessage(), e);
		} finally {
			try {
				if (os != null) {
					os.close();
				}
			} catch(Exception e) {
				logger.error("文件[" + filePath + "]写入失败。" + e.getMessage(), e);
			}
		}
		return "";
	}
	
}
